#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <signal.h>

int main()
{
    //创建监听套接字
    int listenfd = socket(PF_INET, SOCK_STREAM, 0);

    //本程序的IP地址和端口号
    struct sockaddr_in addr;
    addr.sin_family = AF_INET; //IPv4地址（地址类型）
    addr.sin_port = htons(80); //端口号（网络字节序）,程序使用小于1024的端口号需要使用root权限
    addr.sin_addr.s_addr = htonl(INADDR_ANY); //绑定本机所有IP地址
    //addr.sin_addr.s_addr = inet_addr("192.168.1.175"); //指定IP地址进行监听

    //将IP地址与监听套接字绑定
    int error = bind(listenfd, (struct sockaddr*)&addr, sizeof(addr));
    if (error)
    {
        //打印错误原因
        perror("bind");
        return 1;
    }

    error = listen(listenfd, 3);
    if (error)
    {
        perror("listen");
        return 2;
    }

    //忽略SIGPIPE信号，防止发送数据时被OS终止
    signal(SIGPIPE, SIG_IGN);

    //循环服务器
    while(1) //等待下一个客户端连接
    {
        struct sockaddr_in client_addr;
        socklen_t addrlen = sizeof(client_addr);
        //等待客户端连接
        int connectfd = accept(listenfd, (struct sockaddr*)&client_addr, &addrlen);

        printf("client is connected, ip: %s, port: %d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));

        //使用标准IO函数与客户端通信，需要将连接套接字与标准IO文件流绑定
        FILE* fp = fdopen(connectfd, "r+");

        char line[80];
        //循环接收客户端的输入
        while (1)
        {

            while (fgets(line, sizeof(line), fp))
            {
               if(line[0] == '\r')
               {
                   break;
               }
            }

           fprintf(fp, "HTTP/1.1 200 OK\r\n");
           fprintf(fp, "Content-Type: test/plain;charset=utf-8\r\n");
           fprintf(fp, "Content-Length: 12\r\n");
           fprintf(fp, "\r\n");
           fprintf(fp, "Hello world!");
        }

        //断开和客户端的TCP连接
        fclose(fp);
    }
    return 0;
}
